/*
Szymon Rusinkiewicz
Princeton University

rtsc.cc
Real-time suggestive contours
*/

#include "stdafx.h"
//#include "vld.h" //Memory leak detector head file
#include <stdio.h>
#include <stdlib.h>
#include "GL/glui.h"
#include "TriMesh.h"
#include "TriMesh_algo.h"
#include "XForm.h"
#include "GLCamera.h"
#include "timestamp.h"
#include <algorithm>
#include "miinclude.h"
#include "Windows.h"
#include "Commdlg.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include "Wire.h"
#include "math.h"
#include <iostream>

using std::min;
using std::max;
using std::swap;
#define  BIG   100000000000000
//For view segmentation
int  phai=0;
int theta=0;
//#define NEEDSAMPLING 1
#define TWOPI 6.2831852
#define LEFT -1.0
#define RIGHT 1.0
#define BOTTOM -1.0
#define TOP 1.0

#define NOEDGE 255
#define POSSIBLE_EDGE 128
#define EDGE 0
#define Thresh 3

//State of Mouse pressing 
#define STATE_NONE    0 
#define STATE_DRAWING     1
#define STATE_HITING    2 
#define eps 0.000001

#define V_N0 12  //level 0  
#define V_N1 42  //level 1  
#define V_N2 162  //level 2  
#define V_N3 281  //level 3
float VS0[V_N0][3]={0};
float VS1[V_N1][3]={0};
float VS2[V_N2][3]={0};
float VS3[V_N3][3]={0};
float VP0[V_N0][2]={0};
float VP1[V_N1][2]={0};
float VP2[V_N2][2]={0};
float VP3[V_N3][2]={0};
#define DIM V_N2 //42

/*added by libo,20080829,begin*/
//Define the window size
//#define GW 500
//#define GH 500
//int GW=500,GH=500;
//int GW=100,GH=100;
int GW=180,GH=180;
//int GW=50,GH=50;

static float AR;
float scale_ratio=1.0;//1.5; //control the ratio of projection,default [-1.5,1.5]
float  flapcost;
GLUI *glui;
GLenum dm=GL_RENDER; //drawing mode

TriMesh *themesh;
GLCamera camera;
xform xf;
int LIGHTING= TRUE;
int main_win,second_win;
void disp2();
void need_redraw();
//void drawfeaturepoints(vector<Point> Points);
void mymouse(int button, int state, int x, int y);
void reshape1(int w, int h);
void setEnv(); 
void canny_edge(double **BW);
void KeyFunc(unsigned char key, int x, int y);
int  modelfile();
int  modelname();
void quicksort(float arr[],int beg,int end);
void drawmodelfaces();

// Clear the screen and reset OpenGL modes to something sane
void cls()
{
	glDisable(GL_DITHER);
	glDisable(GL_BLEND);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_NORMALIZE);
	glDisable(GL_LIGHTING);
	glDisable(GL_COLOR_MATERIAL);
	glClearColor(1,1,1,0);
	glClearDepth(1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

#define nv DIM //n_theta  //n_theta  //DIM  //n_theta //number of views
float uaxis[3]={0};
float vaxis[3]={0};
float waxis[3]={0};

int current_phai,current_theta;
vector<Point> PV[nv];
// Draw the scene
void disp1()
{
	timestamp t1 = now();
    int i,num1,num2;
	// Set up camera and clear the screen
	GLUI_Master.auto_set_viewport();
	camera.setupGL(xf * themesh->bsphere.center, themesh->bsphere.r);
	cls(); // Clear the screen and reset OpenGL modes to something sane
	point v;
   
	// Draw the mesh using the correct drawing style
	glPushMatrix();
	glMultMatrixd((double *)xf);

	 glPopMatrix();
	 glutSwapBuffers();
	 fflush(stdout);	
	 if (camera.autospin(xf))
		need_redraw();	
}

// Signal a redraw
void need_redraw()
{	
	glutPostRedisplay();
}

 	
  float axis1[3]={1,0,0};  //rotate about X axis for phai
  float axis2[3]={0,1,0};  //rotate about Y axis for theta
  float axis3[3]={0,0,1};  //rotate about Z axis for theta
// Set the view to look at the middle of the mesh, from reasonably far away
int pose=0;
void resetview()
{

	xf=xform::trans(-themesh->bsphere.center);
	//PCA();
       //alignment();
	xf = xf*xform::trans(0, 0, -10.0f * themesh->bsphere.r);
	camera.stopspin();

}


void ComputeCurrentIscoView(int level, int i)
{
	float phai1,theta1;
	switch (level)
	{
	case 0:
		phai1=VP0[i][0];
		theta1=VP0[i][1];
		break;
	case 1:
		phai1=VP1[i][0];
		theta1=VP1[i][1];
		break;
	case 2:
		phai1=VP2[i][0];
		theta1=VP2[i][1];
		break;
	case 3:             
		phai1=VP3[i][0];
		theta1=VP3[i][1];
		break;	
	}	  
	resetview();			
	xf=xf*xform::rot(theta1, axis2[0], axis2[1], axis2[2])*xform::rot(phai1, axis1[0], axis1[1], axis1[2]);
	glutSetWindow(second_win);
	disp2();
}
void RecoverPose(float x, float y, float z)
{
	float phai1,theta1;
	
	phai1=-acos(y/sqrt(x*x+y*y+z*z));
	theta1=-atan2(z, x);
	if (theta1 < 0)
		theta1 = TWOPI - fabs(theta1);
	resetview();			
	xf=xf*xform::rot(theta1, axis2[0], axis2[1], axis2[2])*xform::rot(phai1, axis1[0], axis1[1], axis1[2]);
	glutSetWindow(second_win);
	disp2();
}



void	ReadVerCoor0()
{ 
	int i;
	char line[128]={0};
	float x,y,z, phai1, theta1;
	ifstream fin("..\\Result\\VerCoor-L0.m");
	if (!fin)
	{
        cout << "read fail!" << endl;
        exit(1);
	}
	for(i=0;i<V_N0;i++)
	{
		fin.getline(line,128);
		sscanf(line,"%f,%f,%f",&VS0[i][0],&VS0[i][1],&VS0[i][2]);
		x=VS0[i][0];
		y=VS0[i][1];
		z=VS0[i][2];
		phai1=-acos(y/sqrt(x*x+y*y+z*z));
		theta1=-atan2(z, x);
		if (theta1 < 0)
			theta1 = TWOPI - fabs(theta1);
		VP0[i][0]=phai1;
		VP0[i][1]=theta1;	   
	}	

 }	
void	ReadVerCoor1()
{ 
	int i;
	char line[128]={0};
	float x,y,z, phai1, theta1;	
	ifstream fin("..\\Result\\VerCoor-L1.m");
	if (!fin)
	{
        cout << "read fail!" << endl;
        exit(1);
	}
	for(i=0;i<V_N1;i++)
	{
		fin.getline(line,128);
		sscanf(line,"%f,%f,%f",&VS1[i][0],&VS1[i][1],&VS1[i][2]);	
		x=VS1[i][0];
		y=VS1[i][1];
		z=VS1[i][2];
		phai1=-acos(y/sqrt(x*x+y*y+z*z));
		theta1=-atan2(z, x);
		if (theta1 < 0)
			theta1 = TWOPI - fabs(theta1);
		VP1[i][0]=phai1;
		VP1[i][1]=theta1;	 
	}		
 }	
void	ReadVerCoor2()
{ 
	int i;
	char line[128]={0};
	float x,y,z, phai1, theta1;		
	ifstream fin("..\\Result\\VerCoor-HL2.m");  //reduce the opposite views
	if (!fin)
	{
        cout << "read fail!" << endl;
        exit(1);
	}
	for(i=0;i<V_N2;i++)
	{
		fin.getline(line,128);
		sscanf(line,"%f,%f,%f",&VS2[i][0],&VS2[i][1],&VS2[i][2]);	
		x=VS2[i][0];
		y=VS2[i][1];
		z=VS2[i][2];
		phai1=-acos(y/sqrt(x*x+y*y+z*z));
		theta1=-atan2(z, x);
		if (theta1 < 0)
			theta1 = TWOPI - fabs(theta1);
		VP2[i][0]=phai1;
		VP2[i][1]=theta1;	 
	}		
 }	

 void ReadVerCoor3()
{ 
       int i;
	char line[128]={0};
	float x,y,z, phai1, theta1;	
	ifstream fin("..\\Result\\VerCoor-L3.m");
	if (!fin)
	{
        cout << "read fail!" << endl;
        exit(1);
	}
	for(i=0;i<V_N3;i++)
	{
	fin.getline(line,128);
	sscanf(line,"%f,%f,%f",&VS3[i][0],&VS3[i][1],&VS3[i][2]);	
	x=VS3[i][0];
	y=VS3[i][1];
	z=VS3[i][2];
	phai1=-acos(y/sqrt(x*x+y*y+z*z));
	theta1=-atan2(z, x);
	if (theta1 < 0)
		theta1 = TWOPI - fabs(theta1);
       VP3[i][0]=phai1;
       VP3[i][1]=theta1;	 
	}		
 }	

void InsertIndex(char *des,int index)
{
    char T[4];
    int q,b,s,g;
	
	q=index/1000;
	b=(index-1000*q)/100;
	s=(index-1000*q-100*b)/10;
	g=index-1000*q-100*b-10*s;
	if(index<10)
	{
	     T[0]=char(int('0'+g));
	     strncat(des,T,1);
	}
	else if (index<=99)
	{ 
		T[0]=char(int('0'+s));T[1]=char(int('0'+g));
		strncat(des,T,2);
	}
	else if (index<=999)
	{
		T[0]=char(int('0'+b));T[1]=char(int('0'+s));T[2]=char(int('0'+g));
		strncat(des,T,3);
	}
	else
	{
		T[0]=char(int('0'+q));T[1]=char(int('0'+b));T[2]=char(int('0'+s));T[3]=char(int('0'+g));
		strncat(des,T,4);
	}
}
void quicksort(float arr[],int beg,int end)
{
	if (end  >= beg + 1) 
  	{
  		float piv = arr[beg];
		int k = beg + 1, r = end;
    
		while (k < r) 
    		{
      			if (arr[k] < piv) 
        			k++;
      			else 
        			swap(arr[k], arr[r--]);
    		}
		if (arr[k] < piv){
		
			swap(arr[k],arr[beg]);
			
			quicksort(arr, beg, k);
			quicksort(arr, r, end);			
		}else {
			if (end - beg == 1)
  				return;
  				
			swap(arr[--k],arr[beg]);
			quicksort(arr, beg, k);
			quicksort(arr, r,   end);			
		}
  	}
}


// Handle mouse button and motion events
static unsigned buttonstate = 0;

void mousemotionfunc(int x, int y)
{
	static const Mouse::button physical_to_logical_map[] = {
		Mouse::NONE, Mouse::ROTATE, Mouse::MOVEXY, Mouse::MOVEZ,
		Mouse::MOVEZ, Mouse::MOVEXY, Mouse::MOVEXY, Mouse::MOVEXY,
	};
	Mouse::button b = Mouse::NONE;
	if (buttonstate & (1 << 3))
		b = Mouse::WHEELUP;
	else if (buttonstate & (1 << 4))
		b = Mouse::WHEELDOWN;
	else
		b = physical_to_logical_map[buttonstate & 7];
	//reset here, added by libo
	if (b == Mouse::ROTATE)
	{	
	}
     
	camera.mouse(x, y, b,
		     xf * themesh->bsphere.center, themesh->bsphere.r,
		     xf);

      	 /*
	xf.rot(90/180,0,0,1);
	vec axis(0,0,1);
	rot(themesh,30/180,axis);
       */
	need_redraw();
}

void mousebuttonfunc(int button, int state, int x, int y)
{
	if (state == GLUT_DOWN)
		buttonstate |= (1 << button);
	else
		buttonstate &= ~(1 << button);

	mousemotionfunc(x, y);	
}


// Keyboard callback
void keyboardfunc(unsigned char key, int x, int y)
{
	switch (key) {
		case 'Q':
		case 'q':
			exit(0);		
	}
	need_redraw(); 
	GLUI_Master.sync_live_all();
}

void skeyboardfunc(int key, int x, int y)
{
	need_redraw(); 
	GLUI_Master.sync_live_all();
}


// Reshape the window.  We clear the window here to possibly avoid some
// weird problems.  Yuck.
void reshape(int x, int y)
{
	GLUI_Master.auto_set_viewport();
	cls();
	glutSwapBuffers();
	need_redraw();
}


void usage(const char *myname)
{
	fprintf(stderr, "Usage: %s [-options] infile\n", myname);
	exit(1);
}

float calVisibleSalency()
{
  int i, j, k,index;
  float entropy=0.0;
  //GLenum target , GLboolean reset , GLenum format , GLenum type ;
  //GLvoid *values ;
  //glGetHistogram  (  GL_HISTOGRAM , GL_TRUE ,  GL_RGBA ,  GL_UNSIGNED_BYTE , values ); 

  float *area,m=0,S;
  
  area=new float[themesh->faces.size()];
  for(i=0;i<themesh->faces.size();i++)
  	area[i]=0;
  
  int View[4];
float pixelcolorbuf[200][200][3] ={0}; 
  glutSetWindow(second_win);
  glGetIntegerv(GL_VIEWPORT, View);
  int width = View[2], height = View[3];

  for (i = 0; i < width; i++)
    for (j = 0; j < height; j++)
      for (k = 0; k < 3; k++)
		  pixelcolorbuf[i][j][k] = 0;
  
  glReadBuffer(GL_FRONT);
  glReadPixels(View[0], View[1], width, height, GL_RGB, GL_FLOAT, pixelcolorbuf);
  int U=(int)sqrt((float)themesh->faces.size()); 
  for (i = 0; i < width; i++)
	  for (j = 0; j < height; j++)  
		  if (pixelcolorbuf[i][j][2] == 0.0)   //pixel-level saliency 
		  {
			 // index = int(255 *pixelcolorbuf[i][j][1]) *256+int(255*pixelcolorbuf[i][j][0]);
			  index = int((U-1) *pixelcolorbuf[i][j][1]) *U+int((U-1)*pixelcolorbuf[i][j][0]);
			  area[index]=area[index]+1;			
		  }
		  
  float totalarea=0;
  for(i=0;i<themesh->faces.size();i++)
  {
  	if(area[i]!=0)
		m++;
	totalarea=totalarea+area[i];
  }
  
  //total area
  //S=width*height;  
  //Use the bounding circle
  //S=PI*(width/4.0)*(width/4.0); //  
  //S=(width/2.0)*(height/2.0)
  //S=GW*GH/4;
  //S=PI*25*25;
  
S=GW*GH;//S=totalarea;  
    //S=PI*pow(GW/2.0,2.0);
  float area0=S-totalarea;
  entropy=-(area0/S)*(log(area0/S)/log(2.0));  
   for(i=0;i<themesh->faces.size();i++)
   	if (area[i]!=0)
		entropy=entropy-(area[i]/S)*(log(area[i]/S)/log(2.0));

  //normalization
  //entropy=entropy/(log(m+1)/log(2.0));
  
  return entropy;
}

void ComputeViewEntropy(int level, float*d)
{
	int i;
	for(i=0;i<nv;i++)
	{
		ComputeCurrentIscoView(level,i);
		d[i]=calVisibleSalency();
		//printf("Pose:%d, View Entropy:%f\n",i,d[i]);
	}	
}
void ComputeViewListEntropy(vector <point> &ShortListView, float* dist)
{
	int i;
	for(i=0;i<ShortListView.size();i++)
	{
	
		RecoverPose(ShortListView[i][0],ShortListView[i][1],ShortListView[i][2]);
		dist[i]=calVisibleSalency();
		//printf("Pose:%d, View Entropy:%f\n",i,dist[i]);
	}
}

void dumpserialimages(int index)
{
	FILE* fp;
	char f[128]="..\\Result\\";;
	InsertIndex(f,index);	
	strcat(f,".ppm");
	
	if((fp=fopen(f, "wb"))==NULL);
	{
	//	exit(0);
	}
	
	// Read pixels
	GLint V[4];
	glGetIntegerv(GL_VIEWPORT, V);
	GLint width = V[2], height = V[3];
	char *buf = new char[width*height*3];
	glPixelStorei(GL_PACK_ALIGNMENT, 1);
	glReadPixels(V[0], V[1], width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);

	// Flip top-to-bottom
	for (int i = 0; i < height/2; i++) {
		char *row1 = buf + 3 * width * i;
		char *row2 = buf + 3 * width * (height - 1 - i);
		for (int j = 0; j < 3 * width; j++)
			swap(row1[j], row2[j]);
	}

	// Write out file
	fprintf(fp, "P6\n#\n%d %d\n255\n", width, height);
	fwrite(buf, width*height*3, 1, fp);
	fclose(fp);
	delete [] buf;
}
void ExpandToLowerLevel(point &pos,int level,vector <point> &views)
{
   int i,j;	
   point V;
   float *dist,*sortdist;
   switch(level)
   {
      case 0:   
		  dist=new float[V_N1];
		  sortdist=new float[V_N1];
		  for(i=0;i<V_N1;i++)
		  {
			  dist[i]=pow(VS1[i][0]-pos[0],2)+pow(VS1[i][1]-pos[1],2)+pow(VS1[i][2]-pos[2],2);
			  sortdist[i]=dist[i];
		  }
		  quicksort(sortdist,0,V_N1-1);	
		  for(j=0;j<V_N1;j++)
		  {
			  if(dist[j]<=sortdist[5]+1e-5)
			  {
				  V[0]=VS1[j][0];
				  V[1]=VS1[j][1];
				  V[2]=VS1[j][2]; 			  
				  views.push_back(V);
			  }
		  }
		  break;
      case 1:   	
		  dist=new float[V_N2];
		  sortdist=new float[V_N2];
		  for(i=0;i<V_N2;i++)
		  {
			  dist[i]=pow(VS2[i][0]-pos[0],2)+pow(VS2[i][1]-pos[1],2)+pow(VS2[i][2]-pos[2],2);
			  sortdist[i]=dist[i];		 
		  }
		  quicksort(sortdist,0,V_N2-1);	
		  for(j=0;j<V_N2;j++)
		  {
			  if(dist[j]<=sortdist[5]+1e-5)
			  {
				  V[0]=VS2[j][0];
				  V[1]=VS2[j][1];
				  V[2]=VS2[j][2]; 			  
				  views.push_back(V);
			  }
		  }			  	 
		  break;
		  
      case 2:   	
		  dist=new float[V_N3];
		  sortdist=new float[V_N3];		  
		  for(i=0;i<V_N3;i++)
		  {
			  dist[i]=pow(VS3[i][0]-pos[0],2)+pow(VS3[i][1]-pos[1],2)+pow(VS3[i][2]-pos[2],2);
			  sortdist[i]=dist[i];		 
		  }
		  quicksort(sortdist,0,V_N3-1);	
		  for(j=0;j<V_N3;j++)
		  {
			  if(dist[j]<=sortdist[5]+1e-5)
			  {
				  V[0]=VS3[j][0];
				  V[1]=VS3[j][1];
				  V[2]=VS3[j][2]; 			  
				  views.push_back(V);
			  }
		  }
		  break;		  
   }   	
}
#define step 5
void BruteViewpoint()
{
	int i,j,pos=0;
	
	float theta1, phai1,s,d[(180/step)*(360/step)]={0},sortdist[(180/step)*(360/step)]={0};
	
	for(i=0;i<(180/step);i=i++)
		for(j=0;j<(360/step);j=j++)
		{		      
			phai1=(i*step)/180.0*PI;
			theta1=(j*step)/180.0*PI;
			resetview();			
			xf=xf*xform::rot(theta1, axis2[0], axis2[1], axis2[2])*xform::rot(phai1, axis1[0], axis1[1], axis1[2]);
			glutSetWindow(second_win);
			disp2();	   
			s=calVisibleSalency();
			d[i*(360/step)+j]=s;
			sortdist[i*(360/step)+j]=s;
			printf("phai=%d, theta=%d, View Entropy=%f\n",i*step,j*step,s);
		}		
	quicksort(sortdist,0,(180/step)*(360/step)-1);
	printf("Worst Views:\n"); 
	for(i=0;i<10;i++)
		for(j=0;j<(180/step)*(360/step);j++)
		{
			if(sortdist[i]==d[j])
			{
			       if (i==0)
				   	pos=j;
				printf("No.%d: index=%d,phai=%d, theta=%d, View Entropy=%f\n",i,j,j/(360/step)*step,(j-(360/step)*(j/(360/step)))*step,sortdist[i]);
				break;
			}
		}
	phai1=(pos/(360/step))*step/180.0*PI;
	theta1=(pos-(360/step)*(pos/(360/step)))*step/180.0*PI;
	resetview();			
	xf=xf*xform::rot(theta1, axis2[0], axis2[1], axis2[2])*xform::rot(phai1, axis1[0], axis1[1], axis1[2]);
	glutSetWindow(second_win);
	disp2();	
}
void Viewpoint()
{
	int i,j,pos,level=0;
	float minS=BIG,maxS=0,s;

	float totalsaliency=0.0,visiblesaliency;
	float *dist,*sortdist;
	vector <point> ShortListView;
	point V;
	int* views;
	dist=new float[V_N2];
	sortdist=new float[V_N2];	
		
	timestamp t1 = now();
 	LIGHTING=FALSE;
	
	//Level 0
	printf("\n************Level-0******************\n");
	ComputeViewEntropy(2,dist);
	for(i=0;i<V_N2;i++)
		sortdist[i]=dist[i];	
	quicksort(sortdist,0,V_N2-1);		
	for(j=0;j<V_N2;j++)
	{
		if(sortdist[0]==dist[j])
		{
			printf("Worst View: Pos=%d, View Entropy=%f\n",j,sortdist[0]);
			pos=j;
			break;
		}
	}

	float phai0,theta0;	
	phai0=VP2[pos][0];
	theta0=VP2[pos][1];
	
	//Step: 2D alignment
	float phai1=0,theta1=0,theta2=0,deltatheta=0.0;              
	const float DeltaTheta[5]={PI/3.0,PI/6.0,PI/12.0,PI/36.0,PI/180.0};  //60,30,15,5,1
	float Lower=0, Upper=TWOPI;
	for(level=0;level<4;level++)
	{
		deltatheta=DeltaTheta[level];
		for(theta1=Lower;theta1<Upper;theta1=theta1+deltatheta)
		{
			resetview();			
			xf=xf*xform::rot(theta1, axis2[0], axis2[1], axis2[2])*xform::rot(PI/2.0, axis1[0], axis1[1], axis1[2])*xform::rot(theta0, axis2[0], axis2[1], axis2[2])*xform::rot(phai0, axis1[0], axis1[1], axis1[2]);		
			glutSetWindow(second_win);
			disp2();
			s=calVisibleSalency();			//printf("Pose:%d, View Entropy:%f\n",i,s);
			if (minS>s)
			{
				minS=s;
				theta2=theta1;
			}
		}
		Lower=theta2-deltatheta;
		Upper=theta2+deltatheta;
	}	
	
	LIGHTING=TRUE;
	//Show the final pose
	resetview();	
	xf=xf*xform::rot(-PI/2.0, axis1[0], axis1[1], axis1[2])*xform::rot(theta2, axis2[0], axis2[1], axis2[2])*xform::rot(PI/2.0, axis1[0], axis1[1], axis1[2])*xform::rot(theta0, axis2[0], axis2[1], axis2[2])*xform::rot(phai0, axis1[0], axis1[1], axis1[2]);		
	glutSetWindow(second_win);
	disp2();
	s=calVisibleSalency();
	printf("\n************Result & Performance******************\n");
	printf("\rOptimal pose: %d\nView: (%f,%f,%f)\nDeltatheta=%f\nEntropy: E1=%f, E2=%f\n",pos,V[0],V[1],V[2],deltatheta,dist[pos],minS);
	printf("Elapsed time: %.2f sec.",  (now() - t1));
	delete [] dist;
	delete [] sortdist;
}

void CurrentViewpoint()
{
  LIGHTING=FALSE;
  //disp1();
  glutSetWindow(second_win);
  disp2();
  flapcost=calVisibleSalency();
  glui->sync_live();  
  LIGHTING=TRUE;
}
int main(int argc, char *argv[])
//int main()
{   

	//initialize the GLUT
	glutInitWindowSize(GW,GH);            	//glutInitWindowSize(760, 700);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInit(&argc, argv);

	if (argc < 2)
		usage(argv[0]);

	// Skip over any parameter beginning with a '-'
	int i = 1;
	while (i < argc-1 && argv[i][0] == '-')
		i++;
	const char *filename = argv[i];
	//memset(meshname,0,128);
	//strcpy(meshname,(const)filename);
	//currentmeshname=filename;
	themesh = TriMesh::read(filename);
	//Readpricinpleaxis();	
	ReadVerCoor0();
	ReadVerCoor1();
	ReadVerCoor2();
	ReadVerCoor3();
	if (!themesh)
		usage(argv[0]);
 
	themesh->need_tstrips();
	themesh->need_bsphere();
	themesh->need_bbox();
	themesh->need_normals();
	themesh->need_curvatures();
	themesh->need_dcurv();
	cout<<"Strip Size: "<<themesh->tstrips.size()<<endl;
	cout<<"Vertices Size: "<<themesh->vertices.size()<<endl;
      
   	char windowname[255];
	sprintf(windowname, "RTSC - %s", filename);
	glutInitWindowPosition(50,100);
	main_win = glutCreateWindow(windowname);

	
	printf("main_win=%d\n",main_win);

	glutDisplayFunc(disp1);
	GLUI_Master.set_glutMouseFunc(mousebuttonfunc);
	glutMotionFunc(mousemotionfunc);
	GLUI_Master.set_glutKeyboardFunc(keyboardfunc);
	GLUI_Master.set_glutSpecialFunc(skeyboardfunc);
	GLUI_Master.set_glutReshapeFunc(reshape);

	//GLUI *glui = GLUI_Master.create_glui_subwindow(main_win, GLUI_SUBWINDOW_BOTTOM);
	glui = GLUI_Master.create_glui_subwindow(main_win, GLUI_SUBWINDOW_BOTTOM);
	glui->set_main_gfx_window(main_win);
		
	GLUI_Panel *h = glui->add_panel("3D Alignment");
	glui->add_button_to_panel(h ,"Model Loading ",0,(GLUI_Update_CB)modelfile);
	glui->add_button_to_panel(h ,"Alignment",0,(GLUI_Update_CB)Viewpoint);  //Single ViewContext Comp.  ComputeSingleViewContext  BruteViewpoint
	glui->add_button_to_panel(h ,"Current Viewpont",0,(GLUI_Update_CB)CurrentViewpoint);		
	
	glui->add_column_to_panel(h, false);	
	glui->add_statictext_to_panel(h, "Results:");
	glui->add_edittext_to_panel(h,"Current view area:",GLUI_EDITTEXT_FLOAT,&flapcost,0,NULL);
       glui->add_button_to_panel(h , "Exit", 0, exit);
	resetview();

	// Go through command-line arguments and do what they say.
	for (int i = 1; i < argc-1; i++) 
	{
		if (argv[i][0] != '-')
			break;
		for (unsigned int j = 1; j < strlen(argv[i]); j++)
			keyboardfunc(argv[i][j], 0, 0);
	}

    /***************added by libo,begin***************/
	//create the second  window
	glutInitWindowPosition(700,100);
	second_win=glutCreateWindow("Sketch");
	printf("second_win=%d\n",second_win);
	glViewport(0,0,GW,GH );
	//set the clearcolor and the callback
	glClearColor(0.0,0.0,0.0,1.0);
	glutDisplayFunc(disp2);
	glutReshapeFunc(reshape1);
	glutMouseFunc(mymouse);
	glutKeyboardFunc(KeyFunc);
	//*/
	/**********************added by libo,end*****^****/	 
    glutMainLoop();	
 }
void drawmodelfaces()
{
	int i,index; 
	float depth,lr,z;
	float c;
	int num1,num2;
	 
	glEnable(GL_DEPTH_TEST);
	point center=xf*themesh->bsphere.center;
	float r=themesh->bsphere.r;
	glDisable(GL_LIGHTING); 	
	if (LIGHTING)
		glEnable(GL_LIGHTING); 	
	//glShadeModel(GL_FLAT);	
	glShadeModel(GL_SMOOTH);	
	xform nxf=norm_xf(xf);
	glPolygonMode(GL_FRONT, GL_FILL);
	glPolygonMode(GL_BACK, GL_FILL);
	for (i=0;i<(int)themesh->faces.size();i++)
	{
	    point v1 =xf* themesh->vertices[themesh->faces[i][0]];
		point nn1=nxf*themesh->normals[themesh->faces[i][0]];  //norm_xf(xf)*  transinverse_xf
		point v2 = xf*themesh->vertices[themesh->faces[i][1]];
		point nn2=nxf*themesh->normals[themesh->faces[i][1]];
		point v3 = xf*themesh->vertices[themesh->faces[i][2]];
		point nn3 =nxf* themesh->normals[themesh->faces[i][2]];
			
		glPointSize(1);
		//glBegin(GL_TRIANGLES);	
		glBegin(GL_TRIANGLE_STRIP);
/*		
		num1=i/256;
		num2=i-256*num1;
		glColor3f(num2/255.0,num1/255.0,0.0);
*/
              int U=(int)sqrt((float)themesh->faces.size()); 
		num1=i/U;
		num2=i-U*num1;
		glColor3f(num2/(float)(U-1),num1/(float)(U-1),0.0);
		
		//glColor3f(0.5,0.5,0.5);
		
		/***************first vertex*********************/
		v1=scale_ratio*(v1-center)/r;
		if (LIGHTING)
		glNormal3f(nn1[0], nn1[1], nn1[2]);
		glVertex3fv(v1);			

		
		/***************second vertex*********************/
		v2=scale_ratio*(v2-center)/r;
		if (LIGHTING)
			glNormal3f(nn2[0], nn2[1], nn2[2]);
		glVertex3fv(v2);
		
		/***************third vertex*********************/
		v3=scale_ratio*(v3-center)/r;
		if (LIGHTING)
			glNormal3f(nn3[0], nn3[1], nn3[2]);
		glVertex3fv(v3);
		glEnd();
	} 
}

void drawisocahedra()
{
   int i;
   glBegin(GL_POINTS);
   for (i = 0; i < V_N0; i++) 
   { 
      glVertex3fv(VS0[i]);
   }
   glEnd();
   
}
/*-------------------------------------------------------------------%--------
   Rendering routine
   --------------------------------------------------------------------------*/
void disp2() 
{  
   setEnv(); 
   //glEnable(GL_HISTOGRAM);
   glMatrixMode(GL_PROJECTION); 
   glLoadIdentity(); 
   glOrtho(-AR, AR, -1, 1, -100, 100);   
   glMatrixMode(GL_MODELVIEW); 
   glLoadIdentity(); 
   glDisable(GL_LIGHTING);
   glClearColor (1.0, 1.0, 1.0, 0.0);
   if (themesh!=NULL)
   	drawmodelfaces();
   //ComputeSphericalFeature();
   glutSwapBuffers();
   glutPostRedisplay();
}

 //Load A Model file
int  modelfile()
{

	OPENFILENAME OpenFileName;
	char szFile[MAX_PATH];

    //Create File Browser// 
	szFile[0] = 0;
	
    HWND hwnd= GetActiveWindow();              // owner window
    printf("\nhwnd=%d\n",hwnd);
	OpenFileName.lStructSize = sizeof( OPENFILENAME );
	OpenFileName.hwndOwner = (HWND)hwnd;
	//OpenFileName.lpstrFilter =(LPCSTR)"\PLY(*.ply)\0*.ply\0All Files(.*)\0*.*\0";
	OpenFileName.lpstrFilter =(LPCSTR)"\OFF(*.off)\0*.off\0All Files(.*)\0*.*\0";
	OpenFileName.lpstrCustomFilter = NULL;
	OpenFileName.nMaxCustFilter = 0;
	OpenFileName.nFilterIndex = 0;
	OpenFileName.lpstrFile = (LPSTR)szFile;
	OpenFileName.nMaxFile = sizeof( szFile );
	OpenFileName.lpstrFileTitle = NULL;
	OpenFileName.nMaxFileTitle = 0;
	OpenFileName.lpstrInitialDir = NULL;
	OpenFileName.lpstrTitle = (LPCSTR)"Open a file";
	OpenFileName.nFileOffset = 0;
	OpenFileName.nFileExtension = 0;
	OpenFileName.lpstrDefExt = NULL;
	OpenFileName.lCustData = 0;
	OpenFileName.lpfnHook = NULL;
	OpenFileName.lpTemplateName = NULL;
	OpenFileName.Flags = OFN_EXPLORER;

    //Load model 
	if (GetOpenFileName(&OpenFileName)==TRUE) 
	{
		printf("\n%s\n",szFile);	
		//delete themesh;
		need_redraw();
		themesh = TriMesh::read(szFile);		
		if (themesh!=0)
		{			
			printf("Succussfully loading a model!");		
			//themesh->need_tstrips();
			themesh->need_bsphere();
			//themesh->need_bbox();
			themesh->need_normals();
			//themesh->need_curvatures();
			//themesh->need_dcurv();
			cout<<"Strip Size: "<<themesh->tstrips.size()<<endl;
			cout<<"Vertices Size: "<<themesh->vertices.size()<<endl;	
			cout<<"Faces Size: "<<themesh->faces.size()<<endl;	
			resetview();
			//glutSetWindow(main_win);
			//disp1();
			glutPostRedisplay();
			return TRUE;
		}
		else 
			return FALSE;
	}
	else 
	{   
		printf("Loading file  Failed!");
		return FALSE;
	}	
}

//Load A Model file
int  modelname()
{

	OPENFILENAME OpenFileName;
	char szFile[MAX_PATH];

    //Create File Browser// 
	szFile[0] = 0;
	
    HWND hwnd= GetActiveWindow();              // owner window
    printf("\nhwnd=%d\n",hwnd);
	OpenFileName.lStructSize = sizeof( OPENFILENAME );
	OpenFileName.hwndOwner = (HWND)hwnd;
	//OpenFileName.lpstrFilter =(LPCSTR)"\PLY(*.ply)\0*.ply\0All Files(.*)\0*.*\0";
	OpenFileName.lpstrFilter =(LPCSTR)"\OFF(*.off)\0*.off\0All Files(.*)\0*.*\0";
	OpenFileName.lpstrCustomFilter = NULL;
	OpenFileName.nMaxCustFilter = 0;
	OpenFileName.nFilterIndex = 0;
	OpenFileName.lpstrFile = (LPSTR)szFile;
	OpenFileName.nMaxFile = sizeof( szFile );
	OpenFileName.lpstrFileTitle = NULL;
	OpenFileName.nMaxFileTitle = 0;
	OpenFileName.lpstrInitialDir = NULL;
	OpenFileName.lpstrTitle = (LPCSTR)"Open a file";
	OpenFileName.nFileOffset = 0;
	OpenFileName.nFileExtension = 0;
	OpenFileName.lpstrDefExt = NULL;
	OpenFileName.lCustData = 0;
	OpenFileName.lpfnHook = NULL;
	OpenFileName.lpTemplateName = NULL;
	OpenFileName.Flags = OFN_EXPLORER;

       //Load model 
	if (GetOpenFileName(&OpenFileName)==TRUE) 
	{ 
		//strcpy((char*)currentmeshname,szFile);	
		printf("\n%s\n",szFile);	
		return true;
	}
	else 
		return false;

}


/*---------------------------------------------------------------------------
   Mouse Press p callback routine
   --------------------------------------------------------------------------*/
void mymouse(int button, int state, int x, int y)
{
	;
}

/*---------------------------------------------------------------------------
  Resize the window
  ---------------------------------------------------------------------------*/
void reshape1(int w, int h)
{
  GW = w;
  GH = h;
  AR = (float)(w)/(float)(h);
  glViewport(0, 0, w, h);               /* Set Viewport */   
  glutPostRedisplay();
}

/*---------------------------------------------------------------------------
  Set Rendering Enviroment
   --------------------------------------------------------------------------*/
void setEnv()
{
   glEnable(GL_DEPTH_TEST); 
   // Just clean the screen
   glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); 
   
   // lighting
  // GLfloat light_position[]={ 1.0,1.0,1.0,0.0 };
   GLfloat light_position[]={ 0.0,0.0,1.0,0.0 };

   //GLfloat light_position[]={ 0.0,0.0,10.0,0.0 };
   GLfloat white_light[]={ 1.0,1.0,1.0,1.0 };
   GLfloat lmodel_ambient[]={ 1.0,0.1,0.1,1.0 };
   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
   glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);

   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
   glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);
   

   //Setup the camera
   glMatrixMode(GL_MODELVIEW); 
   glLoadIdentity(); 
   gluLookAt(0,0,20,0,0,0,0,1,0); 
   
    // setup the perspective projectin
   if (dm == GL_SELECT)
   {
	 glMatrixMode(GL_PROJECTION); 
	 //glLoadIdentity(); 
	 glOrtho(-AR, AR, -1, 1, -100, 100);
    }
}
/*---------------------------------------------------------------------------
   Key events function 
   --------------------------------------------------------------------------*/
void KeyFunc(unsigned char key, int x, int y)
{
  char sketch=0;
  switch(key)
  {      
 case 'q':
 case 'Q':
	 exit(0);
	 break;
  }
  glutPostRedisplay();
}
